package emulator.shell.GUI.profiling;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.swing.tree.TreeNode;

import emulator.assembler.AddressDictionary;
import emulator.hardware.HwWord;
import emulator.hardware.debug.profiling.CodeSegment;

public class CallTreeModelData implements TreeNode
{
	private CallTreeModelData parent = null;
	private List<CallTreeModelData> children = new ArrayList<CallTreeModelData>();
	private String label;
	private int address;

	public CallTreeModelData()
	{
		label = "";
		address = -1;
	}

	public CallTreeModelData(CodeSegment codeSegment, AddressDictionary labelMap, Set<CodeSegment> visited)
	{
		label = labelMap.getLabel(codeSegment.getEnterAddress())
				+ " ($" + new HwWord(codeSegment.getEnterAddress())
				+ " ,#=" + codeSegment.getCallCount()
				+ " ,Tot.=" + codeSegment.getSumTicks()
				+ " ,Seg.=" + (codeSegment.getSumTicks() - codeSegment.getSubTicks()) + ")";
		address = codeSegment.getEnterAddress();
		if (!visited.contains(codeSegment))
		{
			visited.add(codeSegment);
			for (CodeSegment child : codeSegment.getChildren())
			{
				children.add(new CallTreeModelData(child, labelMap, visited));
			}
			visited.remove(codeSegment);
		}
	}
	
	@Override
	public String toString()
	{
		return label;
	}
	
	@Override
	public TreeNode getChildAt(int childIndex)
	{
		return children.get(childIndex);
	}

	@Override
	public int getChildCount()
	{
		return children.size();
	}

	@Override
	public TreeNode getParent()
	{
		return parent;
	}

	@Override
	public int getIndex(TreeNode node)
	{
		return children.indexOf(node);
	}

	@Override
	public boolean getAllowsChildren()
	{
		return true;
	}

	@Override
	public boolean isLeaf()
	{
		return children.isEmpty();
	}

	@Override
	public Enumeration<CallTreeModelData> children()
	{
		return Collections.enumeration(children);
	}

	public void addChild(CodeSegment codeSegment, AddressDictionary labelMap)
	{
		children.add(new CallTreeModelData(codeSegment, labelMap, new HashSet<CodeSegment>()));
	}

	public int getAddress()
	{
		return address;
	}
}
